package com.dding.cms.base.web.widget;

import static com.dding.cms.base.web.ActionConstants.WIDGET_SEPERATOR;

import java.util.Iterator;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;

import org.dding.core.log.ILogger;
import org.dding.core.log.LoggerFactory;
import org.dding.core.util.StringUtils;

public class WidgetController {

	private ILogger logger = LoggerFactory.getLogger(WidgetController.class);
	private static WidgetController INSTANCE = new WidgetController();
	private ConcurrentHashMap<String, IWidgetHandler> handlers = new ConcurrentHashMap<String, IWidgetHandler>();

	protected WidgetController() {
		ServiceLoader<IWidgetHandler> serviceLoader = ServiceLoader.load(
				IWidgetHandler.class, WidgetController.class.getClassLoader());
		Iterator<IWidgetHandler> it = serviceLoader.iterator();
		while (it.hasNext()) {
			IWidgetHandler handler = it.next();
			registerWidget(handler);
		}
	}

	public static WidgetController getInstance() {
		return INSTANCE;
	}

	public synchronized void registerWidget(IWidgetHandler handler) {
		String id = getId(handler);
		if (StringUtils.isNotEmpty(id)) {
			handlers.put(id, handler);
			logger.debug("register widget handler " + id);
		}
		String[] fields = getFileds(handler);
		if (fields != null) {
			for (String field : fields) {
				handlers.put(field, handler);
				logger.debug("register widget handler " + field);
			}
		}
		String name = getTable(handler);
		if (StringUtils.isNotEmpty(name)) {
			handlers.put(name, handler);
			logger.debug("register widget handler " + name);
		}
	}

	public synchronized void removeWidget(IWidgetHandler handler) {

		String id = getId(handler);
		if (StringUtils.isNotEmpty(id)) {
			if (handlers.remove(id) != null) {
				logger.debug("remove widget handler " + id);
			}
		}
		String[] fields = getFileds(handler);
		if (fields != null) {
			for (String field : fields) {
				if (handlers.remove(field) != null) {
					logger.debug("remove widget handler " + field);
				}
			}
		}
		String name = getTable(handler);
		if (StringUtils.isNotEmpty(name)) {
			if (handlers.remove(name) != null) {
				logger.debug("remove widget handler " + name);
			}
		}
	}

	public IWidgetHandler getWidgetByTypeAndName(String widgetType, String name) {
		IWidgetHandler handler = null;
		if (StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(widgetType)) {
			handler = handlers.get(name + WIDGET_SEPERATOR + widgetType);
		}
		if (handler == null) {
			return handlers.get(widgetType);
		}
		return handler;
	}

	public IWidgetHandler getWidgetByTable(String table) {
		IWidgetHandler handler = null;
		if (StringUtils.isNotEmpty(table)) {
			handler = handlers.get(table);
		}
		return handler;
	}

	public IWidgetHandler getWidgetByTableField(String field) {
		IWidgetHandler handler = null;
		if (StringUtils.isNotEmpty(field)) {
			handler = handlers.get(field);
		}
		return handler;
	}

	private String getId(IWidgetHandler handler) {
		Widget widget = handler.getClass().getAnnotation(Widget.class);
		if (widget == null)
			return null;
		return widget.Id();
	}

	private String[] getFileds(IWidgetHandler handler) {
		WidgetField fields = handler.getClass()
				.getAnnotation(WidgetField.class);
		if (fields == null)
			return null;
		return fields.values();
	}

	private String getTable(IWidgetHandler handler) {
		WidgetTable table = handler.getClass().getAnnotation(WidgetTable.class);
		if (table == null)
			return null;
		return table.value();
	}
}
